﻿//     Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace Microsoft.Gateway.Utils
{
    public class SharedCache
    {
        const string CacheFileExtension = ".cache";
        const string CacheResourceName  = "ConfigurationCache";

        public enum CacheClasses
        {
            GatewayConfiguration,
            ServiceName,
            UpdateCheckSeed,
        }

        public SharedCache()
        {
            this.CacheLocation = AzureUtils.GetLocalResourceLocation(CacheResourceName);
        }

        public SharedCache(string cacheLocation)
        {
            this.CacheLocation = cacheLocation;
        }

        public static SharedCache Create(string cacheLocation = null)
        {
            if (String.IsNullOrWhiteSpace(cacheLocation))
            {
                return new SharedCache();
            }
            else
            {
                return new SharedCache(cacheLocation);
            }
        }

        public string CacheLocation { get; set; }

        public static T ReadCachedObject<T>(CacheClasses cacheClass, string cacheLocation = null)
        {
            return Create(cacheLocation).ReadObject<T>(cacheClass);
        }

        public T ReadObject<T>(CacheClasses cacheClass)
        {
            string cachePath = GetClassFilename(cacheClass);
            if (!File.Exists(cachePath))
            {
                return default(T);
            }
            try
            {
                using (var reader = new JsonTextReader(File.OpenText(cachePath)))
                {
                    return new JsonSerializer().Deserialize<T>(reader);
                }
            }
            catch (Exception ex)
            {
                Trace.TraceWarning("Failure reading local cache file [{0}]. Details: {1}", cachePath, ex);
            }
            return default(T);
        }

        public static bool WriteObjectToCache<T>(CacheClasses cacheClass, T itemToStore, string cacheLocation = null)
        {
            return Create(cacheLocation).WriteObject<T>(cacheClass, itemToStore);
        }

        public bool WriteObject<T>(CacheClasses cacheClass, T itemToStore)
        {
            string cachePath = GetClassFilename(cacheClass);
            try
            {
                using (var writer = File.CreateText(cachePath))
                {
                    var serializer = new JsonSerializer
                    {
                        Formatting = Formatting.Indented,
                    };
                    serializer.Serialize(writer, itemToStore);
                    return true;
                }
            }
            catch (Exception ex)
            {
                Trace.TraceWarning("Failure writing local cache file [{0}]. Details: {1}", cachePath, ex);
            }
            return false;
        }

        string GetClassFilename(CacheClasses cacheClass)
        {
            return Path.Combine(this.CacheLocation, Path.ChangeExtension(cacheClass.ToString(), CacheFileExtension));
        }
    }
}
